<?php

namespace app\common\model;

use app\common\lib\Redis;
use app\common\model\Follow as FollowModel;
use app\common\utils\Str;
use catcher\exceptions\FailedException;
use app\common\model\search\PatientInfoSearch;
use app\common\model\CollectCase as CollectCaseModel;
use app\common\model\CollectClass as CollectClassModel;
use catchAdmin\permissions\model\Users as UsersModel;
use MongoDB\BSON\ObjectId;
use app\common\model\Relation as RelationModel;
use app\common\model\Contract as ContractModel;
use app\common\lib\ZhyxMongo;
use think\Paginator;
use app\common\business\Follow as followBusiness;

class PatientInfo extends BaseModel
{
    use PatientInfoSearch;

    protected $name = "patient_info";

    protected $type = [
        'inage' => 'integer',
        'mobile' => 'integer',
        'created_at' => 'integer',
        'updated_at' => 'integer',
    ];

    /**
     * 获取器-入院途径
     * @return string
     */
    public function getInhospitalWayAttr($value, $data): string
    {
        $arr = [1 => "急诊", 2 => "门诊", 3 => "其它医疗机构转入", 9 => "其他"];
        return $arr[$value] ?? "其他";
    }

    /**
     * 获取器-联系人关系
     * @return array
     */
    public function getRelationInfoAttr($value, $data): array
    {

        $relation = (new RelationModel())->column('relationName', 'relationType');

        $rets = [];
        foreach ($value as $k => $v) {

            $v['relationName'] = $v['relationTypeName'] ?? '其他';

            $mobile = $v["mobile"];
            if (!empty($mobile) && $mobile[0] !== "1" || mb_strlen($mobile) !== 11) {
                $mobile = str_replace("-", "", $v["mobile"]);
                $mobile = mb_substr($mobile, 0, 4) . "-" . mb_substr($mobile, 4);
            }
            $v["mobile"] = $mobile;
            $rets[] = $v;
        }
        return $rets;
    }


    /**
     * 获取数据列表
     * @return array
     */
    public function getList(): array
    {

        $rdsCondition = '';
        $requestId = (string)new ObjectId();
        $limit = request()->param("limit", 20, 'int');
        $page = request()->param("page", 1, 'int');
        $rTotalCount = request()->param("total_count", 0, 'int');
        $type = request()->param('type', 1, 'int');

        switch ($type) {
            case 1:
                $order = 'outList.visitTime';
                break;
            case 2:
                $order = 'inList.inhospitalDate';
                break;
            case 3:
                $order = 'hoList.outhospitalDate';
                break;
            default:
                $order = '_id';
                break;
        }
        $list = [];
        $lastPage = 0;

        if ($rTotalCount === 0) {

            $totalCount = $this->mongoSearch([], [], ['limit', 'page', 'total_count', 'request_id'])->count();

            if ($totalCount > 0) {
                $lastPage = ceil($totalCount / $limit);
            }
        } else {
            $totalCount = $rTotalCount;
        }

        if (!empty(request()->param('request_id'))) {

            $rnd = Redis::getInstance()->redis->get("advSearch:" . request()->param('request_id'));

            $sql = $this->getLastSql();

            $pattern = '/"query":(.*),\"limit/';

            preg_match($pattern, $sql, $matches);

            if (isset($matches[1]) && !empty($matches[1])) {
                $condition = array_merge_recursive(json_decode($rnd, true), json_decode($matches[1], true));
                $rdsCondition = json_encode($condition, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
                $skip = ($page - 1) * $limit;
                $pip = ZhyxMongo::getInstance()->setCollection('patient_info');
                $totalCount = $pip->countDocuments($condition);
                if ($totalCount > 0) {
                    $lastPage = ceil($totalCount / $limit);
                    $list = $pip->find($condition, ["skip" => $skip, 'limit' => $limit]);
                    $list = iterator_to_array($list);
                }
            }
        } else {

            $list = $this->mongoSearch([], [], ['limit', 'page', 'total_count'])
                ->order($order, 'desc')
                ->page($page)
                ->limit($limit)
                ->select();
        }

        if (!empty($list) && $page == 1) {
            $reqId = request()->param('request_id', "", "string");
            if (empty($reqId)) {
                $sql = $this->getLastSql();
                $pattern = '/find\((.*})\)\.sort/';
                preg_match($pattern, $sql, $matches);
                if (isset($matches[1]) && !empty($matches[1])) {

                    Redis::getInstance()->redis->setex("patient_data:" . $requestId, 3600, $matches[1]);
                }
            } else {
                Redis::getInstance()->redis->setex("patient_data:" . $requestId, 3600, $rdsCondition);
            }
        }
        return [
            'total' => $totalCount,
            'per_page' => 0,
            'current_page' => $page ?: 1,
            'last_page' => $lastPage,
            'request_id' => $requestId,
            'data' => $list
        ];
    }


    /**
     * 添加数据
     * @param array $data
     * @return string
     */
    public function addData(array $data): string
    {
        //添加时销毁自带的主键id
        //unset($data['id']);
        return $this->save($data);
    }

    /**
     * 更新数据
     * @param array $data
     * @return bool
     */
    public function saveData($id, array $data): bool
    {
        $model = self::find($id);
        return $model->save($data);
    }

    public function exportList()
    {
        $fieldMapping = $this->getFieldByType();

        $ret = $this->mongoSearch()
            ->where($this->getUserJurisdiction(request()->param('type', 1)))
            ->field($fieldMapping["fields"])
            ->select();
        return $ret;

    }

    public function getFieldByType(): array
    {
        $type = request()->param("type", "", "string");
        $arr = [];
        switch ($type) {
            case "1":
                $arr = [
                    "fields" => ["id" => '$id', "clinicNo" => '$outList.clinicNo' ?? '', "name" => '$name', "sex" => '$sex', "birthdate" => '$birthdate', "liveStatus" => '$liveStatus', "presentTelphone" => '$presentTelphone', "attendingDoctorName" => '$outList.attendingDoctorName', "deptName" => '$outList.deptName', "visitTime" => '$outList.visitTime', "diagnosis" => '$outList.diagnose'],
                    "field_text" => ["门诊号", "患者姓名", "性别", "出生日期", "生存状态", "电话", "就诊医生", "就诊科室", "就诊日期", "门诊诊断"],
                    "title" => "outList",
                    'endPoint' => 'J'
                ];
                break;
            case "2":
                $arr = [
                    "fields" => ["id" => '$id', "inhospitalId" => '$inList.inhospitalNo', "name" => '$name', "sex" => '$sex', "birthdate" => '$birthdate', "liveStatus" => '$liveStatus', "presentTelphone" => '$presentTelphone', "inchargeDoctorName" => '$inList.inchargeDoctorName', "inhospitalDate" => '$inList.inhospitalDate', 'inhospitalDeptCode' => '$inList.inhospitalDeptCode', 'inhospitalWard' => '$inList.inhospitalWard', 'inhospitalWay' => '$inList.inhospitalWay', "diagnose" => '$inList.diagnose'],
                    "field_text" => ["住院号", "姓名", "性别", "出生日期", "生存状态", "电话", "主治医师", "入院日期", "入院科室", "入院病区", "入院途径", "入院诊断"],
                    "title" => "inList",
                    'endPoint' => 'L'
                ];
                break;
            case "3":
                $arr = [
                    "fields" => ["id" => '$id', "inhospitalId" => '$hoList.inhospitalNo', "name" => '$name', "sex" => '$sex', "birthdate" => '$birthdate', "liveStatus" => '$liveStatus', "presentTelphone" => '$presentTelphone', "inchargeDoctorName" => '$hoList.inchargeDoctorName', "outhospitalDate" => '$hoList.outhospitalDate', 'inhospitalDeptCode' => '$hoList.inhospitalDeptCode', 'outhospitalWard' => '$hoList.inhospitalWard', "diagnose" => '$outList.diagnose'],
                    "field_text" => ["住院号", "姓名", "性别", "出生日期", "生存状态", "电话", "主治医师", "出院日期", "出院科室", "出院病区", "入院诊断"],
                    "title" => "hoList",
                    'endPoint' => 'K'
                ];
                break;
            default:
                throw new FailedException("暂不支持该类型的导出");
                break;
        }
        return $arr;
    }

    /**
     * 患者ID获取数据
     * @param string $patient_id
     */
    public function getInfo($patient_id, $filed = "*")
    {
        $patientInfo = $this->where('patientId', $patient_id)->field($filed)->find();
        if (empty($patientInfo)) {
            throw new FailedException("患者信息不存在");
        }
        $patientInfo["patient_uuid"] = $patientInfo["id"];
        unset($patientInfo["id"]);
        return $patientInfo;
    }

    /**
     * 主键获取数据
     * @param string $id
     */
    public function getWhereId(string $id, string $field = '*')
    {
        $field = 'name,sex,inage,nation,idType,idno,presentTelphone,birthdate,birthplaceProvince,birthplacecity,birthplacecounty,nativeProvince,nativecity,accountProvince,accountCity,accountCounty,accountAddress,presentProvince,presentcity,presentcounty,presentAddress,contactName,contactAddress,relationTypeName,contactTelphone,medicalRecordsNo,bz';
        $row = $this->where('id', $id)->field($field)->find();

        if (!$row) {
            throw new FailedException('患者不存在');
        }

        //计算年龄
        $row['inage'] = '';
        if (!empty($row['birthdate'])) {
            $row['inage'] = floor((time() - strtotime($row['birthdate'])) / 31556926); // 计算年龄
        }

        //出生地
        $row['birthplace'] = $row['birthplaceProvince'] . $row['birthplacecity'] . $row['birthplacecounty'];
        //籍贯
        $row['nativeplace'] = $row['nativeProvince'] . $row['nativecity'];
        //户籍
        $row['registered'] = $row['accountProvince'] . $row['accountCity'] . $row['accountCounty'] . $row['accountAddress'];
        //现住址
        $row['current'] = $row['presentProvince'] . $row['presentcity'] . $row['presentcounty'] . $row['presentAddress'];

        return $row;
    }

    /**
     * 按条件获取患者
     * @param int $type 1 收案患者，2 随访患者
     * @return array
     */
    public function getWherePatient(int $type): array
    {
        $req = request()->param();
        $page = request()->param("page", 1, "int");
        $limit = request()->param("limit", 10, "int");
        $requestId = request()->param("request_id", "", "string");

        $patientId = (new CollectCaseModel())->getKeyVal([], 'patientId');

        $users = $this->getUserJurisdiction('');
        if (!empty($users)) {
            if (strpos($users[0][0], '|') !== false) {
                $match['$or'] = [
                    ['outList.attendingDoctorId' => ['$in' => $users[0][2]]],
                    ['inList.inchargeDoctorNo' => ['$in' => $users[0][2]]],
                    ['hoList.inchargeDoctorNo' => ['$in' => $users[0][2]]]
                ];
            } else {
                $match[$users[0][0]] = ['$in' => $users[0][2]];
            }
        }
        $match['patientId'] = ['$nin' => $patientId];
        $match['liveStatus'] = '1';
        $match['deleted_at'] = 0;

        if (!empty($requestId)) {
            $rnd = Redis::getInstance()->redis->get("advSearch:" . $req['request_id']);
            $rndArr = json_decode($rnd, true, 512, JSON_THROW_ON_ERROR);
            $match = array_merge_recursive($match, $rndArr);

        } else {
            //获取筛选条件
            $search = (new followBusiness())->getFollowScreenItem($req);

            //获取配置条件
            $match = array_merge_recursive($match, $search);
        }

        $pip = [['$match' => $match], ['$project' => ['_id' => true, 'id' => '$_id', 'patientId' => '$patientId', 'name' => '$name', 'sex' => '$sex', 'birthdate' => '$birthdate', 'presentTelphone' => '$presentTelphone', 'medicalRecordsNo' => '$medicalRecordsNo', 'bz' => ['$ifNull' => [['$arrayElemAt' => ['$bz.bingzhongArr.bingzhong_name', 0]], '']], 'diagnosis' => ['$ifNull' => ['$inList.diagnose', '']], 'diseaseNo' => ['$ifNull' => ['$inList.diseaseNo', '']], 'first_treat_datetime' => ['$ifNull' => ['$first_treat_datetime', '']], 'first_treat_age' => ['$ifNull' => ['$first_treat_age', '']], 'follow_time' => ['$ifNull' => ['$follow_node.follow_time', '']], 'taskname' => ['$ifNull' => ['$establish_followtask_node.taskname', '']], 'follow_result' => ['$ifNull' => ['$follow_node.resultName', '']]]], ['$sort' => ['_id' => -1]], ['$skip' => (($page - 1) * $limit)], ['$limit' => $limit]];

        $pipCount = [['$match' => $match], ['$count' => 'total_count']];

        //聚合总数
        $total = $this->mongoAggregate($pipCount);

        $totalCount = 0;
        foreach ($total as $key => $val) {
            $totalCount = $val["total_count"];
        }

        //聚合数据
        $data = $this->mongoAggregate($pip);

        $ret = [];
        foreach ($data as $key => $val) {
            $val['id'] = (string)$val['id'];
            $ret[] = $val;
        }

        return [
            "count" => $totalCount,
            "current" => $page,
            "limit" => 10,
            "data" => $ret
        ];
    }

    /**
     * 获取患者信息，门诊信息，住院信息数据和统计次数
     * @param string $id 患者信息主键_id
     * @return array
     */
    public function getInOutData(string $id): array
    {
        //患者信息
        $data['info'] = $this->where('id', $id)->field('patientId,name,sex,inage,presentTelphone,liveStatus,is_in_hospital,birthdate')->find();

        //计算年龄
        if (!empty($data['info']['birthdate'])) {
            $data['info']['inage'] = floor((time() - strtotime($data['info']['birthdate'])) / 31556926); // 计算年龄
        }

        //门诊
        $data['outNum'] = (new PatientRecord())->getTypeCount($data['info']['patientId'], 1);
        $outfield = 'id,visitTime,diseaseName';
        $data['outList'] = (new PatientRecord())->getWhereType($data['info']['patientId'], 1, $outfield, 'visitTime');

        //住院
        $data['inNum'] = (new PatientRecord())->getTypeCount($data['info']['patientId'], 3);
        $infield = 'id,inhospitalDate,outhospitalDate,diagnose,inhospitalNo';
        $data['inList'] = (new PatientRecord())->getWhereType($data['info']['patientId'], 3, $infield, 'inhospitalDate');

        return $data;
    }

    /**
     * 号码维护列表
     * @param string $id 主键
     * @return array
     */
    public function getNumberList(string $id): array
    {
        //查询号码维护字段
        $relation = $this->where('id', $id)->field('relationInfo')->find();

        if (!$relation) {
            throw new FailedException("患者不存在");
        }

        $relation = $relation->toArray();

        $ret = [];

        //没有联系人返回空
        if (!isset($relation['relationInfo'])) {
            return $ret;
        }

        $sort = array_column($relation['relationInfo'], 'default');

        if (count($sort) > 1) {
            array_multisort($sort, SORT_DESC, $relation['relationInfo']);
        }
        return $relation['relationInfo'];
    }

    /**
     * 添加号码维护
     */
    public function addNumber($id, $param = [])
    {
        $relation = $this->where('id', $id)->field('relationInfo')->find()->toArray();

        $sid = new ObjectId();

        if (isset($relation['relationInfo']) && !empty($relation['relationInfo'])) {

            //默认联系人
            if ($param['default'] == 1) {
                $newArr = [];
                foreach ($relation['relationInfo'] as $k => $v) {
                    $v['default'] = 0;
                    $newArr[] = $v;
                }
                $data['relationInfo'] = $newArr;
            } else {
                $data['relationInfo'] = $relation['relationInfo'];
            }

            $data['relationInfo'][] = [
                'sid' => (string)$sid,
                'relation' => $param['relation'],
                'name' => $param['name'],
                'mobile' => $param['mobile'],
                'inhospitalWay' => $param['inhospitalWay'],
                'default' => $param['default'],
            ];
        } else {
            $data['relationInfo'][] = [
                'sid' => (string)$sid,
                'relation' => $param['relation'],
                'name' => $param['name'],
                'mobile' => $param['mobile'],
                'inhospitalWay' => $param['inhospitalWay'],
                'default' => $param['default'],
            ];
        }
        sort($data['relationInfo']);
        return $this->saveData($id, $data);
    }

    /**
     * 更新号码维护
     */
    public function upNumber($id, $param = [])
    {
        try {
            $relation = $this->where('id', $id)->field('relationInfo')->find()->toArray();

            foreach ($relation['relationInfo'] as $k => $v) {
                if ($v['sid'] == $param['sid']) {
                    unset($relation['relationInfo'][$k]);
                }
            }

            //默认联系人
            if ($param['default'] == 1) {
                $newArr = [];
                foreach ($relation['relationInfo'] as $k => $v) {
                    $v['default'] = 0;
                    $newArr[] = $v;
                }
                $data['relationInfo'] = $newArr;
            } else {
                $data['relationInfo'] = $relation['relationInfo'];
            }

            $data['relationInfo'][] = [
                'sid' => $param['sid'],
                'relation' => $param['relation'],
                'name' => $param['name'],
                'mobile' => $param['mobile'],
                'inhospitalWay' => $param['inhospitalWay'],
                'default' => $param['default'],
            ];
            sort($data['relationInfo']);
            $this->saveData($id, $data);

            //如果是本人，同步更新患者电话号
            if ($param['relation'] == 0) {
                $this->saveData($id, ['presentTelphone' => $param['mobile']]);
                $followInfo = (new FollowModel())->where('pid', $id)->find();
                if ($followInfo) {
                    (new FollowModel())->where('pid', $id)->update(['presentTelphone' => $param['mobile']]);
                }
            }
            return true;
        } catch (\Exception $exception) {
            throw new FailedException($exception->getMessage());
        }
    }

    /**
     * 删除号码维护
     */
    public function delNumber($id, $param = [])
    {
        $relation = $this->where('id', $id)->field('relationInfo')->find()->toArray();

        foreach ($relation['relationInfo'] as $key => $val) {
            if ($val['sid'] == $param['sid']) {
                unset($relation['relationInfo'][$key]);
            }
        }

        $data['relationInfo'] = $relation['relationInfo'];
        sort($data['relationInfo']);
        return $this->saveData($id, $data);
    }

    /**
     * 标记死亡
     */
    public function upDeath(array $param)
    {
        $datas = [];
        foreach ($param['pid'] as $key => $val) {
            $data['id'] = $val;

            //是否死亡 1 健在，2 死亡
            $data['liveStatus'] = "0";

            $datas[] = $data;
        }
        (new CollectClassModel())->pullNode($param['pid']);
        return $this->saveAll($datas);
    }

    /**
     * 在院宣教数据
     * @param int $tag 标签： 1 查询列表 2查询数据
     */
    public function getInEducation(int $tag = 1)
    {
        $req = request()->param();

        //类型：1 住院，2 出院
        if (isset($req['type']) && $req['type'] == 1) {
            $where = $this->getUserJurisdiction(2);
            $where[] = ['is_in_hospital', '=', 1];
            $order = 'inList.inhospitalDate';
        } elseif (isset($req['type']) && $req['type'] == 2) {
            $where = $this->getUserJurisdiction(3);
            $where[] = ['is_in_hospital', '=', 2];
            $order = 'hoList.outhospitalDate';
        } else {
            throw new FailedException('暂无数据');
        }

        if ($tag == 2) {
            return $this->mongoSearch([], [], ['ed', 'pushtime', 'mode', 'batch_name', 'all', 'type', 'sms_id'])
                ->where($where)
                ->field('id,patientId,name')
                ->select()
                ->each(function ($item, $key) {
                    $item['pid'] = $item['id'];
                    return $item;
                })
                ->toArray();
        } else {
            return $this->mongoSearch([], [], ['type'])
                ->where($where)
                ->field('id,patientId,patient_id,birthdate,name,sex,first_treat_age,presentTelphone,inList.inhospitalDate,inList.inchargeDoctorName,medicalRecordsNo,inList.diagnose,inList.ch,inList.qualityControlNurseName,is_in_hospital,calc_date_node,hoList.outhospitalDate')
                ->order($order, 'desc')
                ->paginate($this->pageLimit)
                ->each(function ($item, $key) {
                    $inhospitalDate = date('Y-m-d', strtotime($item['inList']['inhospitalDate']));
                    $item['inchargeDoctorName'] = $item['inList']['inchargeDoctorName'] ?? '';
                    $item['diagnose'] = $item['inList']['diagnose'] ?? '';
                    $item['inhospitalDate'] = $inhospitalDate;
                    $item['ch'] = $item['inList']['ch'] ?? '';
                    $item['qualityControlNurseName'] = $item['inList']['qualityControlNurseName'] ?? '';
                    if ($item['is_in_hospital'] == 1) {
                        $day = Str::calculateDays($inhospitalDate, date('Y-m-d'));
                    } else {
                        $outhospitalDate = date('Y-m-d', strtotime($item['hoList']['outhospitalDate']));
                        $item['outhospitalDate'] = $outhospitalDate;
                        $day = Str::calculateDays($inhospitalDate, $outhospitalDate);
                    }
                    $item['inDay'] = $day;

                    //换算年龄
                    $item['inage'] = '';
                    if (!empty($item['birthdate'])) {
                        $item['inage'] = floor((time() - strtotime($item['birthdate'])) / 31556926); // 计算年龄
                    }
                    unset($item['inList']);
                    return $item;
                });
        }

    }

    public function getPatientListByUids(array $userIds = [], $field = "*")
    {
        $arr = [];
        $result = ZhyxMongo::getInstance()->setCollection($this->name)->aggregate([['$match' => ['patientId' => ['$in' => $userIds], 'deleted_at' => 0]], ['$group' => ['_id' => '$patientId', 'name' => ['$first' => '$name'], 'presentTelphone' => ['$first' => '$presentTelphone'], 'patientId' => ['$first' => '$patientId']]]]);
        if (!empty($result)) {
            foreach ($result as $k => $v) {
                $arr[] = (array)$v;
            }
        }
        return $arr;
    }

    public function getPatientListByUid(array $userIds = [], $field = "*")
    {
        return $this->where("patientId", "in", $userIds)->field($field)->select();

    }

    /**
     * 患者id获取患者基本信息
     * @param  $patientId
     * @param  $type 1 首页，2 详情, 3 用户全部信息
     */
    public function getPatientInfo($patientId, $type = "")
    {
        switch ($type) {
            case 1:
                $field = 'patientId,name,presentTelphone,sex';
                $row = $this->where('patientId', $patientId)->field($field)->find();
                if ($row) {
                    $row['presentTelphone'] = $this->desensitize($row['presentTelphone'], 3, 4);
                }
                break;
            case 2:
                $field = 'patientId,name,presentTelphone,sex,idno,birthdate';
                $row = $this->where('patientId', $patientId)->field($field)->find();
                if ($row) {
                    $row['presentTelphone'] = $this->desensitize($row['presentTelphone'], 3, 4);
                    $row['idno'] = $type == 2 ? $this->desensitize($row['idno'], 2, 12) : '';
                }
                break;
            default:
                $field = '*';
                $row = $this->where('patientId', $patientId)->field($field)->find();

        }
        return $row;
    }


    public function getPatientInfoByCard(string $idCard)
    {
        $field = 'patientId,name,presentTelphone,sex';
        return $this->where('idno', $idCard)->field($field)->find();

    }

    /**
     * 数据脱敏
     */
    private function desensitize($string, $start = 0, $length = 0, $re = '*')
    {
        if (empty($string) || empty($length) || empty($re)) return $string;
        $end = $start + $length;
        $strlen = mb_strlen($string);
        $str_arr = array();
        for ($i = 0; $i < $strlen; $i++) {
            if ($i >= $start && $i < $end)
                $str_arr[] = $re;
            else
                $str_arr[] = mb_substr($string, $i, 1);
        }
        return implode('', $str_arr);
    }

    /**
     * 患者端号码维护列表
     */
    public function getPatientIdRelation($patientId)
    {
        $inhospitalWay = config('dictionary.inhospitalWay');
        $relation = $this->where('patientId', $patientId)->field('relationInfo')->find();
        $data = [];
        if (isset($relation['relationInfo']) && !empty($relation['relationInfo'])) {
            $arr = $relation->toArray();
            foreach ($arr['relationInfo'] as $key => $val) {
                $one['sid'] = $val['sid'];
                $one['name'] = $val['name'];
                $one['mobile'] = $this->desensitize($val['mobile'], 3, 4);
                $one['relation'] = (new RelationModel)->getOne($val['relation']);
                $one['default'] = $val['default'];
                $one['inhospitalWay'] = $inhospitalWay[$val['inhospitalWay']] ?? '其他';
                $data[] = $one;
            }
        }
        $sort = array_column($data, 'default');
        array_multisort($sort, SORT_DESC, $data);
        return $data;
    }

    /**
     * 获取家庭成员详情
     */
    public function getRelationDetailed($patientId, $sid)
    {
        $relation = $this->where('patientId', $patientId)->field('id,relationInfo')->find();

        $data = [];
        if (isset($relation['relationInfo']) && !empty($relation['relationInfo'])) {
            foreach ($relation['relationInfo'] as $key => $val) {
                if ($sid == $val['sid']) {
                    $data = $val;
                }
            }
        }
        return $data;
    }

    /**
     * 医生工号获取患者列表
     * @param array $param 参数
     * @return Paginator
     */
    public function getDoctorPatient(array $param): Paginator
    {
        $caseModel = (new CollectCaseModel());
        $user_id = $param['user_id'];
        return $this//->mongoSearch()
        // ->whereOr('outList.attendingDoctorId', $param['doctor_code'])
        // ->whereOr('inList.inchargeDoctorNo', $param['doctor_code'])
        // ->whereOr('hoList.inchargeDoctorNo', $param['doctor_code'])
        ->field('name,patientId,inage,timeLine,sex,created_ymd')
            ->paginate($this->pageLimit)
            ->each(function ($item, $key) use ($caseModel, $user_id) {
                //患者是否被医生收案关注
                $where[] = ['pid', '=', $item['id']];
                $where[] = ['attention', '=', $user_id];
                $caseInfo = $caseModel->where($where)->field('id,attention,created_at')->find();

                if (isset($caseInfo['attention']) && !empty($caseInfo['attention'])) {
                    $attention = 1;
                } else {
                    $attention = 0;
                }
                $item['collect_id'] = $caseInfo['id'] ?? '';
                $item['attention'] = $attention;
                $item['caseDate'] = $caseInfo['created_at'] ?? '';
                $item['diagnosis'] = $item['timeLine'][0]['diagnosis'] ?? '';
                return $item;
            });
    }

    /**
     * 医生端获取患者顶部信息
     */
    public function getPatientTop($patientId)
    {
        $info = $this->where('patientId', $patientId)->field('id,patientId,name,presentTelphone,sex,monitor')->find();

        $classList = (new CollectClassModel)->where('type', 1)->whereNotNull('patientList')->field('className,patientList')->select()->toArray();

        $className = '';
        foreach ($classList as $key => $val) {
            foreach ($val['patientList'] as $k => $v) {
                if ($v['patient_id'] == $info['patientId']) {
                    $className .= $val['className'];
                }
            }
        }

        //是否签约
        $isqy = (new ContractModel)->where('patientId', $patientId)->findOrEmpty()->toArray();
        $info['contract'] = $isqy ? '已签约' : '未签约';
        $info['presentTelphone'] = $this->desensitize($info['presentTelphone'], 3, 4);
        $info['className'] = !empty($className) ? $className : '未分组';
        return $info;
    }

    /**
     * 医生获取所属死亡患者
     */
    public function getDoctorDie()
    {
        $users = $this->getUserIds();
        if (!empty($users)) {
            $doctors = (new UsersModel)->whereIn('id', $users)->column('doctor_code');
            return $this->whereOr('outList.attendingDoctorId', 'in', $doctors)
                ->whereOr('inList.inchargeDoctorNo', 'in', $doctors)
                ->where('liveStatus', '0')
                ->field('name,sex,patientId,inList.diagnose,deathDate,causeOfDeath')
                ->order('deathDate', 'desc')
                ->select();
        } else {
            return $this->where('liveStatus', '0')
                ->field('name,sex,patientId,inList.diagnose,deathDate,causeOfDeath')
                ->order('deathDate', 'desc')
                ->select();
        }
    }

    /**
     * 获取条件匹配的数据
     * @param array $where 条件
     * @param string $field 字段
     * @return array
     */
    public function getConditionData(array $where = [], string $field = "*"): array
    {
        return $this->mongoSearch()->field($field)->where($where)->select()->toArray();
    }

    /**
     * 获取条件匹配的数据(自定义搜索器)
     * @param array $where 条件
     * @param string $field 字段
     * @return Paginator
     */
    public function getSearchConditionData(array $where = [], string $field = "*", string $sort = '_id'): Paginator
    {
        return $this->mongoSearch()->where($where)->field($field)->order($sort, 'desc')->paginate($this->pageLimit);
    }

    /**
     * 获取条件匹配的字段数组(自定义搜索器)
     * @param array $where 条件
     * @param string $field 字段
     * @return array
     */
    public function getSearchConditionColumn(array $where = [], string $field = "patientId"): array
    {
        return $this->mongoSearch([], [], ['ratio'])->where($where)->column($field);
    }

    /**
     * 获取条件匹配的统计数
     * @param array $where 条件
     * @return int
     */
    public function getConditionCount(array $where = []): int
    {
        return $this->mongoSearch([], [], ['ratio'])->where($where)->count();
    }

    /**
     * 获取数据
     * @param array $where 条件
     * @param string $field 字段
     */
    public function getOneData(array $where = [], string $field = "*", string $order = "created_at")
    {
        return $this->where($where)->field($field)->order($order, 'desc')->find();
    }

    /**
     * 获取条件匹配的统计数(不加搜索器)
     * @param array $where 条件
     * @return int
     */
    public function getNoSearchCount(array $where = []): int
    {
        return $this->where($where)->count();
    }

    /**
     * 获取条件匹配的统计数(不加搜索器)
     * @param array $where 条件
     * @param string $field 字段
     * @return array
     */
    public function getNoSearchData(array $where = [], string $field = "*"): array
    {
        return $this->where($where)->field($field)->select()->toArray();
    }

    /**
     * 获取条件匹配的列表(不加搜索器)
     * @param array $where 条件
     * @param string $field 字段
     * @return Paginator
     */
    public function getNoSearchList(array $where = [], string $field = "*"): Paginator
    {
        return $this->where($where)->field($field)->paginate($this->pageLimit);
    }

    /**
     * mongo更新array类型字段
     * @param string $id 主键
     * @param string $idField 主键字段名
     * @param string $field 字段
     * @param string $fieldValue 字段值
     * @return bool
     */
    public function setToData(string $idField, string $id, string $field, string $fieldValue): bool
    {
        try {
            ZhyxMongo::getInstance()->setCollection($this->name)->updateOne([$idField => $id], ['$set' => [$field => $fieldValue]]);
            return true;
        } catch (\Exception $exception) {
            throw new FailedException($exception->getMessage());
        }
    }

    public function getAllPatientIds(string $groupIds, int $userId, string $value = 'patientId', int $type = 1, bool $isFilterDie = false): array
    {

        $patientIds = [];
        $condition = [];
        $where = [];
        $users = $this->getUserJurisdiction('');
        if (!empty($users)) {
            $where = $users;
        }

        if (strtoupper($groupIds) === "NO") {

            $patientQuery = ZhyxMongo::getInstance()->setCollection("collect_class")->aggregate([['$match' => ['creator_id' => $userId, 'deleted_at' => 0]], ['$project' => ['patientIds' => '$patientList.patient_id']], ['$unwind' => ['path' => '$patientIds']], ['$group' => ['_id' => null, 'patientIds' => ['$addToSet' => '$patientIds']]]]);
            foreach ($patientQuery as $k => $v) {
                if (!empty($v["patientIds"])) {
                    $patientIds = (array)$v["patientIds"];
                }
            }
            if (!empty($patientIds)) {
                $condition[] = ["patientId", "not in", $patientIds];

            }
        } else if ($groupIds !== "" && $groupIds !== "ALL") {
            $patientIds = [];
            $xpath = (new CollectClassModel())->where("id", "=", $groupIds)->find();

            $groupIdsArr = [$groupIds];
            if (!empty($xpath)) {
                $groupIdsArr = (new CollectClassModel())->where("xpath", 'like', $xpath["xpath"])->column("id");

            }
            $patientQuery = (new CollectClass())->where("id", "in", $groupIdsArr)->field(["patientList.patient_id"])->select()->toArray();

            if (!empty($patientQuery)) {
                foreach ($patientQuery as $pk => $pv) {
                    if (isset($pv["patientList"])) {
                        foreach ($pv["patientList"] as $k => $v) {
                            $patientIds[] = $v["patient_id"];
                        }
                    }
                }
            }

            if (!empty($patientIds)) {
                $condition[] = ["patientId", "in", $patientIds];
            } else {
                throw new FailedException("分组下没有患者");
            }
        }
        $patientNewIds = (new CollectCaseModel())->where($condition)->column('patientId');
        $where[] = ["patientId", "in", $patientNewIds];

        if ($type == 2) {
            return (new PatientInfo())->where($where)->field($value)->select()->toArray();
        }
        if ($isFilterDie) {
            $where[] = ["liveStatus", "=", "1"];
        }
        return (new PatientInfo())->where($where)->column($value);

    }

    /**
     * mongodb聚合查询
     * @param array $pip 条件
     * @return array
     */
    public function mongoAggregate(array $pip = []): array
    {
        $data = ZhyxMongo::getInstance()->setCollection($this->name)->aggregate($pip);
        return iterator_to_array($data);

    }


}
